home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 79 / maccd 79.iso / multimedial / GL Tron / Source / gltron / model.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-05-13  |  11.4 KB  |  414 lines  |  [TEXT/CWIE]

  1. #include "model.h"
  2. #include "geom.h"
  3.  
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7.  
  8. #define MAX_V 30000
  9. #define MAX_F 20000
  10. #define MAX_N 30000
  11.  
  12. #define FAIL(X) free(vert); free(face); free(norm); free(normi); \
  13.                 printf(X); return NULL;
  14.  
  15. void rescaleVertices(float *vertices, float size, int nVertices, float *bbox) {
  16.   float x, y, z, xmax, ymax, zmax, max;
  17.   float *f;
  18.   int i;
  19.  
  20.   /* printf("rescaling %d vertices\n", nVertices); */
  21.  
  22.   if(nVertices == 0) return;
  23.   x = *(vertices);
  24.   y = *(vertices + 1);
  25.   z = *(vertices + 2);
  26.  
  27.   for(i = 0; i < nVertices; i++) {
  28.     f = vertices + 3 * i;
  29.     if(*f < x)
  30.       x = *f;
  31.     if(*(f + 1) < y)
  32.       y = *(f + 1);
  33.     if(*(f + 2) < z)
  34.       z = *(f + 2);
  35.   }
  36.   xmax = 0; ymax = 0; zmax = 0;
  37.   for(i = 0;  i < nVertices; i ++) {
  38.     f = vertices + 3 * i;
  39.     *f = *f - x;
  40.     *(f + 1) = *(f + 1) - y;
  41.     *(f + 2) = *(f + 2) - z;
  42.     if(*f > xmax) xmax = *f;
  43.     if(*(f + 1) > ymax) ymax = *(f + 1);
  44.     if(*(f + 2) > zmax) zmax = *(f + 2);
  45.   }
  46.   if(xmax + ymax + zmax == 0) return;
  47.  
  48.   if (xmax > ymax)
  49.     max = (xmax > zmax) ? xmax : zmax;
  50.   else
  51.     max = (ymax > zmax) ? ymax : zmax;
  52.  
  53.   for(i = 0;  i < nVertices; i ++) {
  54.     f = vertices + 3 * i;
  55.     *f = *f / max * size;
  56.     *(f + 1) = *(f + 1) / max * size;
  57.     *(f + 2) = *(f + 2) / max * size;
  58.   }
  59.   
  60.   bbox[0] = xmax / max * size;
  61.   bbox[1] = ymax / max * size;
  62.   bbox[2] = zmax / max * size;
  63.  
  64.  
  65.   printf("translated model by (%f, %f, %f)\n", x, y, z);
  66.   printf("scaled model down by %f\n", max * size);
  67.   printf("bounding box: (0, 0, 0) - (%.2f, %.2f, %.2f)\n",
  68.      bbox[0], bbox[1], bbox[2]);
  69.  
  70. }
  71.   
  72. Mesh* loadModel(const char *filename, float size, int flags) {
  73.   /* faces: only quads or triangles at the moment */
  74.   Mesh* mesh;
  75.   Material *materials;
  76.  
  77.   FILE *f;
  78.   char buf[120];
  79.   char namebuf[120];
  80.   char *path;
  81.  
  82.   float *vert;
  83.   int *face;
  84.   float *norm;
  85.   int *normi;
  86.   int *matIndex;
  87.   
  88.   float *vertex, *normal;
  89.  
  90.   int nNormals = 0;
  91.   int nVertices = 0;
  92.   int nFaces = 0;
  93.  
  94.   float *meshVerts;
  95.   float *meshNorms;
  96.   int *meshFacesize;
  97.   int currentMat = 0;
  98.   int matCount = 0;
  99.   int *pMatCount = NULL;
  100.   int iLine = 0;
  101.  
  102.   float t1[3], t2[3], t3[3];
  103.   int c, i, j, k, l, pos;
  104.   int hasNorms = 0;
  105.   int hasTexture = 0;
  106.   int inv;
  107.  
  108.   if((f = fopen(filename, "r")) == 0) {
  109.     fprintf(stderr, "could not open file\n");
  110.     return NULL;
  111.   }
  112.  
  113.   vert = (float *) malloc(sizeof(float) * 3 * MAX_V);
  114.   face = (int *) malloc(sizeof(int) * MODEL_FACESIZE * MAX_F);
  115.   matIndex = (int *) malloc(sizeof(int) * MAX_F);
  116.   normi = (int *) malloc(sizeof(int) * MODEL_FACESIZE * MAX_F);
  117.   norm = (float *) malloc(sizeof(float) * 3 * MAX_N);
  118.   
  119.   while(fgets(buf, sizeof(buf), f)) {
  120.     switch(buf[0]) {
  121.     case 'm': /* material library? */
  122.       if(sscanf(buf, "mtllib %s ", namebuf) == 1) {
  123.     /* load material library */
  124.     path = getFullPath(namebuf);
  125.     if(path == NULL) {
  126.       fprintf(stderr, "fatal: can't find mtllib '%s'\n", namebuf);
  127.       exit(1);
  128.     }
  129.     matCount = loadMaterials(path, &materials);
  130.     if(matCount <= 0) {
  131.       fprintf(stderr, "fatal: no Materials loaded\n");
  132.       exit(1);
  133.     }
  134.     /* printf("loaded %d Materials\n", matCount); */
  135.     pMatCount = (int*) malloc(sizeof(int) * matCount);
  136.     for(i = 0; i < matCount; i++)
  137.       pMatCount[i] = 0;
  138.     currentMat = 0;
  139.       } else
  140.     fprintf(stderr, "warning: ignored line %d\n", iLine);
  141.       break;
  142.     case 'u': case 'g': /* material name */
  143.       if(sscanf(buf, "usemtl %s ", namebuf) == 1) {
  144.     for(i = 0; i < matCount; i++) {
  145.       if(strcmp(namebuf, (materials + i)->name) == 0) {
  146.         currentMat = i;
  147.         break; /* break out of if */
  148.       }
  149.     }
  150.       } else currentMat = 0;
  151.       break;
  152.     case 'v':
  153.       switch(buf[1]) {
  154.       case ' ': /* vertex data */
  155.     if(nVertices >= MAX_V) {
  156.       FAIL("vertex limit exceeded\n") ;
  157.     }
  158.     c = sscanf(buf, "v %f %f %f ",
  159.            vert + nVertices * 3,
  160.            vert + nVertices * 3 + 1,
  161.            vert + nVertices * 3 + 2);
  162.  
  163.     for(i = c; i < 3; i++) {
  164.       printf("this should not happen\n");
  165.       *(vert + nVertices * 3 + i) = 0;
  166.     }
  167.     nVertices++;
  168.     break;
  169.       case 'n': /* vertex normal */
  170.     hasNorms = 1;
  171.     if(nVertices >= MAX_N) {
  172.       FAIL("normals limit exceeded\n") ;
  173.     }
  174.     c = sscanf(buf, "vn %f %f %f ", 
  175.            norm + nNormals * 3,
  176.            norm + nNormals * 3 + 1,
  177.            norm + nNormals * 3 + 2);
  178.     for(i = c; i < 3; i++) {
  179.       printf("this should not happen\n");
  180.       *(norm + nNormals * 3 + i) = 0;
  181.       break;
  182.     }
  183.     nNormals++;
  184.     break;
  185.       case 't': /* texture coordinate - ignored */
  186.     hasTexture = 1;
  187.     break;
  188.       }
  189.       break;
  190.     case 'f':
  191.       if(nFaces * MODEL_FACESIZE >= MAX_F) {
  192.     FAIL("face limit exceeded\n") ;
  193.       }
  194.       /* mark material */
  195.       *(matIndex + nFaces) = currentMat;
  196.       if(matCount > 0 && pMatCount != NULL)
  197.     pMatCount[currentMat]++;
  198.  
  199.       if(hasNorms) {
  200.     int dummy1, dummy2, dummy3, dummy4;
  201.     if (hasTexture) {
  202.       c = sscanf(buf, "f %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d ",
  203.              face + nFaces * MODEL_FACESIZE, &dummy1,
  204.              normi + nFaces * MODEL_FACESIZE,
  205.              face + nFaces * MODEL_FACESIZE + 1, &dummy2,
  206.              normi + nFaces * MODEL_FACESIZE + 1,
  207.              face + nFaces * MODEL_FACESIZE + 2, &dummy3,
  208.              normi + nFaces * MODEL_FACESIZE + 2,
  209.              face + nFaces * MODEL_FACESIZE + 3, & dummy4,
  210.              normi + nFaces * MODEL_FACESIZE + 3); 
  211.     } else {
  212.       c = sscanf(buf, "f %d//%d %d//%d %d//%d %d//%d ",
  213.              face + nFaces * MODEL_FACESIZE,
  214.              normi + nFaces * MODEL_FACESIZE,
  215.              face + nFaces * MODEL_FACESIZE + 1,
  216.              normi + nFaces * MODEL_FACESIZE + 1,
  217.              face + nFaces * MODEL_FACESIZE + 2,
  218.              normi + nFaces * MODEL_FACESIZE + 2,
  219.              face + nFaces * MODEL_FACESIZE + 3,
  220.              normi + nFaces * MODEL_FACESIZE + 3);
  221.     }
  222.  
  223.     for(i = c / 2; i < MODEL_FACESIZE; i++) {
  224.       *(face + nFaces * MODEL_FACESIZE + i) = -1;
  225.       *(normi + nFaces * MODEL_FACESIZE + i) = -1;
  226.     }
  227.  
  228.     nFaces++;
  229.       } else {
  230.     /* TODO: add if(hasTexture) */
  231.     c = sscanf(buf, "f %d %d %d %d ",
  232.            face + nFaces * MODEL_FACESIZE,
  233.            face + nFaces * MODEL_FACESIZE + 1,
  234.            face + nFaces * MODEL_FACESIZE + 2,
  235.            face + nFaces * MODEL_FACESIZE + 3);
  236.     for(i = c; i < MODEL_FACESIZE; i++)
  237.       *(face + nFaces * MODEL_FACESIZE + i) = -1;
  238.     nFaces++;
  239.       }
  240.       break;
  241.     }
  242.     iLine++;
  243.   }
  244.   if(hasNorms == 0) {
  245.     /* create Normals */
  246.     for(i = 0; i < nFaces; i++) {
  247.       t1[0] = *(vert + 3 * (*(face + i * MODEL_FACESIZE + 0) - 1) + 0);
  248.       t1[1] = *(vert + 3 * (*(face + i * MODEL_FACESIZE + 0) - 1) + 1);
  249.       t1[2] = *(vert + 3 * (*(face + i * MODEL_FACESIZE + 0) - 1) + 2);
  250.  
  251.       t2[0] = *(vert + 3 * (*(face + i * MODEL_FACESIZE + 1) - 1) + 0);
  252.       t2[1] = *(vert + 3 * (*(face + i * MODEL_FACESIZE + 1) - 1) + 1);
  253.       t2[2] = *(vert + 3 * (*(face + i * MODEL_FACESIZE + 1) - 1) + 2);
  254.  
  255.       t3[0] = *(vert + 3 * (*(face + i * MODEL_FACESIZE + 2) - 1) + 0);
  256.       t3[1] = *(vert + 3 * (*(face + i * MODEL_FACESIZE + 2) - 1) + 1);
  257.       t3[2] = *(vert + 3 * (*(face + i * MODEL_FACESIZE + 2) - 1) + 2);
  258.       /*
  259.       printf("face %d:\n", i);
  260.       printf("v1: %f %f %f\n", t1[0], t1[1], t1[2]);
  261.       printf("v2: %f %f %f\n", t2[0], t2[1], t2[1]);
  262.       printf("v3: %f %f %f\n", t3[0], t3[1], t3[1]);
  263.       */
  264.       t1[0] -= t3[0];
  265.       t1[1] -= t3[1];
  266.       t1[2] -= t3[2];
  267.       t2[0] -= t3[0];
  268.       t2[1] -= t3[1];
  269.       t2[2] -= t3[2];
  270.       normcrossprod(t1, t2, t3);
  271.       /* printf("normal: %f %f %f\n\n", t3[0], t3[1], t3[2]); */
  272.       /* t3 now contains the face normal */
  273.       for(j = 0; j < MODEL_FACESIZE; j++) 
  274.     *(normi + i * MODEL_FACESIZE + j) = nNormals + 1;
  275.       *(norm + nNormals * 3 + 0) = t3[0];
  276.       *(norm + nNormals * 3 + 1) = t3[1];
  277.       *(norm + nNormals * 3 + 2) = t3[2];
  278.       nNormals++;
  279.     }
  280.     /* printf("generated %d normals\n", nNormals); */
  281.   }
  282.  
  283.  
  284.   if(matCount == 0) { /* create Default material */
  285.     float spec[] = { 0.77, 0.77, 0.77, 1.0 };
  286.     float dif[] = { 0.4, 0.4, 0.4, 1};
  287.     float amb[] = { 0.25, 0.25, 0.25, 1};
  288.  
  289.     materials = (Material*) malloc(sizeof(Material));
  290.     materials->name = (char*) malloc(strlen("default") + 1);
  291.     sprintf(materials->name, "default");
  292.     
  293.     memcpy(materials->ambient, amb, 3 * sizeof(float));
  294.     memcpy(materials->diffuse, dif, 3 * sizeof(float));
  295.     memcpy(materials->specular, spec, 3 * sizeof(float));
  296.  
  297.     matCount = 1;
  298.     pMatCount = (int*) malloc(sizeof(int));
  299.     pMatCount[0] = nFaces;
  300.   }
  301.   /* everything is parsed, now allocate memory and */
  302.   /* rescale and get bbox */
  303.   /* copy data to Mesh structure */
  304.   /* new: sort into sub meshes with by materials */
  305.  
  306.   if(flags & 1) { /* invert normals */
  307.     /* printf("inverting normals...really!\n"); */
  308.     inv = -1;
  309.   } else inv = 1;
  310.  
  311.   mesh = (Mesh*) malloc(sizeof(Mesh));
  312.  
  313.   /* rescale */
  314.  
  315.   rescaleVertices(vert, size, nVertices, mesh->bbox);
  316.  
  317.   mesh->nFaces = nFaces;
  318.   mesh->nMaterials = matCount;
  319.   mesh->materials = materials;
  320.   mesh->meshparts = (MeshPart*) malloc(matCount * sizeof(MeshPart));
  321.   for(i = 0; i < matCount; i++) {
  322.     meshVerts = (float*) malloc(pMatCount[i] * 3 * MODEL_FACESIZE * sizeof(float));
  323.     meshNorms = (float*) malloc(pMatCount[i] * 3 * MODEL_FACESIZE * sizeof(float));
  324.     meshFacesize = (int*) malloc(pMatCount[i] * sizeof(int));
  325.  
  326.     /* printf("Material %d: %d faces\n", i, pMatCount[i]); */
  327.  
  328.     (mesh->meshparts + i)->nFaces = pMatCount[i];
  329.     (mesh->meshparts + i)->vertices = meshVerts;
  330.     (mesh->meshparts + i)->normals = meshNorms;
  331.     (mesh->meshparts + i)->facesizes = meshFacesize;
  332.     pos = 0;
  333.     for(j = 0; j < nFaces; j++) { /* foreach face */
  334.       if(matIndex[j] == i) {
  335.     *(meshFacesize + pos) = 0;
  336.     /* printf("face %d\n", j); */
  337.     for(k = 0; k < MODEL_FACESIZE; k++) { /* foreach vertex of face */
  338.       if(*(face + j * MODEL_FACESIZE + k) != -1) {
  339.         *(meshFacesize + pos) += 1;
  340.         /* adjust facesize... */
  341.         /* copy face and normal data to meshVerts, meshNorms */
  342.         vertex = vert + 3 * ( *(face + j * MODEL_FACESIZE + k) - 1);
  343.         normal = norm + 3 * ( *(normi + j * MODEL_FACESIZE + k) - 1);
  344.         for(l = 0; l < 3; l++) {
  345.           /* printf("%f ", vertex[l]); */
  346.           *(meshVerts + 3 * (pos * MODEL_FACESIZE + k) + l) = *(vertex + l);
  347.           *(meshNorms + 3 * (pos * MODEL_FACESIZE + k) + l) = inv * *(normal + l);
  348.         }
  349.         /* printf("\n"); */
  350.       }
  351.  
  352.     }
  353.     pos++;
  354.     if(pos > pMatCount[i]) {
  355.       fprintf(stderr, "fatal: more faces than accounted for\n");
  356.       exit(1);
  357.     }
  358.       }
  359.     }
  360.   }
  361.   
  362.   free(vert);
  363.   free(face);
  364.   free(norm);
  365.   free(normi);
  366.   free(pMatCount);
  367.   free(matIndex);
  368.  
  369.   /* printf("loaded model: %d vertices, %d normals, %d faces, %d materials\n",
  370.     nVertices, nNormals, nFaces, matCount); */
  371.  
  372.   return mesh;
  373. }
  374.  
  375. void setMaterialAmbient(Mesh *mesh, int material, float color[4]) {
  376.   int i;
  377.   for(i = 0; i < 4; i++)
  378.     (mesh->materials + material)->ambient[i] = color[i];
  379. }
  380.  
  381. void setMaterialDiffuse(Mesh *mesh, int material, float color[4]) {
  382.   int i;
  383.   for(i = 0; i < 4; i++)
  384.     (mesh->materials + material)->diffuse[i] = color[i];
  385. }
  386.  
  387. void setMaterialSpecular(Mesh *mesh, int material, float color[4]) {
  388.   int i;
  389.   for(i = 0; i < 4; i++)
  390.     (mesh->materials + material)->specular[i] = color[i];
  391. }
  392.   
  393. void setMaterialAlphas(Mesh *mesh, float alpha) {
  394.   int i;
  395.   /* vertex alpha is the alpha of the diffuse material component */
  396.   for(i = 0; i < mesh->nMaterials; i++)
  397.     (mesh->materials + i)->diffuse[3] = alpha;
  398. }
  399.  
  400. void unloadModel(Mesh *mesh) {
  401.   int i;
  402.   for(i = 0; i < mesh->nMaterials; i++) {
  403.     /* free material */
  404.     free( (mesh->materials + i)->name );
  405.     free( (mesh->materials + i) );
  406.     /* free meshpart */
  407.     free( (mesh->meshparts + i)->facesizes );
  408.     free( (mesh->meshparts + i)->vertices );
  409.     free( (mesh->meshparts + i)->normals );
  410.     free( (mesh->meshparts + i) );
  411.   }
  412. }
  413.   
  414.